/*
 * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.sun.corba.se.impl.orb;

import java.net.URL;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.ServerSocket;

import java.io.IOException;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;

import org.omg.PortableInterceptor.ORBInitializer;
import org.omg.PortableInterceptor.ORBInitInfo;

import com.sun.corba.se.pept.broker.Broker;
import com.sun.corba.se.pept.encoding.InputObject;
import com.sun.corba.se.pept.encoding.OutputObject;
import com.sun.corba.se.pept.protocol.MessageMediator;
import com.sun.corba.se.pept.transport.Acceptor;
import com.sun.corba.se.pept.transport.Connection;
import com.sun.corba.se.pept.transport.ContactInfo;
import com.sun.corba.se.pept.transport.ContactInfoList;
import com.sun.corba.se.pept.transport.EventHandler;
import com.sun.corba.se.pept.transport.InboundConnectionCache;

import com.sun.corba.se.spi.ior.IOR;
import com.sun.corba.se.spi.ior.ObjectKey;
import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
import com.sun.corba.se.spi.logging.CORBALogDomains;
import com.sun.corba.se.spi.orb.ORB;
import com.sun.corba.se.spi.orb.Operation;
import com.sun.corba.se.spi.orb.OperationFactory;
import com.sun.corba.se.spi.orb.ParserData;
import com.sun.corba.se.spi.orb.ParserDataFactory;
import com.sun.corba.se.spi.orb.StringPair;
import com.sun.corba.se.spi.transport.CorbaContactInfoList;
import com.sun.corba.se.spi.transport.CorbaContactInfoListFactory;
import com.sun.corba.se.spi.transport.CorbaTransportManager;
import com.sun.corba.se.spi.transport.IORToSocketInfo;
import com.sun.corba.se.spi.transport.ReadTimeouts;
import com.sun.corba.se.spi.transport.SocketInfo;
import com.sun.corba.se.spi.transport.IIOPPrimaryToContactInfo;
import com.sun.corba.se.spi.transport.TransportDefault;

import com.sun.corba.se.impl.encoding.CodeSetComponentInfo;
import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
import com.sun.corba.se.impl.legacy.connection.USLPort;
import com.sun.corba.se.impl.logging.ORBUtilSystemException;
import com.sun.corba.se.impl.oa.poa.BadServerIdHandler;
import com.sun.corba.se.impl.orbutil.ORBConstants;
import com.sun.corba.se.impl.protocol.giopmsgheaders.KeyAddr;
import com.sun.corba.se.impl.protocol.giopmsgheaders.ProfileAddr;
import com.sun.corba.se.impl.protocol.giopmsgheaders.ReferenceAddr;
import com.sun.corba.se.impl.transport.DefaultIORToSocketInfoImpl;
import com.sun.corba.se.impl.transport.DefaultSocketFactoryImpl;

import sun.corba.SharedSecrets;

/**
 * Initialize the parser data for the standard ORB parser.  This is used both
 * to implement ORBDataParserImpl and to provide the basic testing framework
 * for ORBDataParserImpl.
 */
public class ParserTable {

  private static String MY_CLASS_NAME = ParserTable.class.getName();

  private static ParserTable myInstance = new ParserTable();

  private ORBUtilSystemException wrapper;

  public static ParserTable get() {
    return myInstance;
  }

  private ParserData[] parserData;

  public ParserData[] getParserData() {
    ParserData[] parserArray = new ParserData[parserData.length];
    System.arraycopy(parserData, 0, parserArray, 0, parserData.length);
    return parserArray;
  }

  private ParserTable() {
    wrapper = ORBUtilSystemException.get(CORBALogDomains.ORB_LIFECYCLE);

    String codeSetTestString =
        OSFCodeSetRegistry.ISO_8859_1_VALUE + "," +
            OSFCodeSetRegistry.UTF_16_VALUE + "," +
            OSFCodeSetRegistry.ISO_646_VALUE;

    String[] debugTestData = {"subcontract", "poa", "transport"};

    USLPort[] USLPorts = {new USLPort("FOO", 2701), new USLPort("BAR", 3333)};

    ReadTimeouts readTimeouts =
        TransportDefault.makeReadTimeoutsFactory().create(
            ORBConstants.TRANSPORT_TCP_INITIAL_TIME_TO_WAIT,
            ORBConstants.TRANSPORT_TCP_MAX_TIME_TO_WAIT,
            ORBConstants.TRANSPORT_TCP_GIOP_HEADER_MAX_TIME_TO_WAIT,
            ORBConstants.TRANSPORT_TCP_TIME_TO_WAIT_BACKOFF_FACTOR);

    ORBInitializer[] TestORBInitializers =
        {null,
            new TestORBInitializer1(),
            new TestORBInitializer2()};
    StringPair[] TestORBInitData = {
        new StringPair("foo.bar.blech.NonExistent", "dummy"),
        new StringPair(MY_CLASS_NAME + "$TestORBInitializer1", "dummy"),
        new StringPair(MY_CLASS_NAME + "$TestORBInitializer2", "dummy")};

    Acceptor[] TestAcceptors =
        {new TestAcceptor2(),
            new TestAcceptor1(),
            null};
    // REVISIT: The test data gets put into a Properties object where
    // order is not guaranteed.  Thus the above array is in reverse.
    StringPair[] TestAcceptorData = {
        new StringPair("foo.bar.blech.NonExistent", "dummy"),
        new StringPair(MY_CLASS_NAME + "$TestAcceptor1", "dummy"),
        new StringPair(MY_CLASS_NAME + "$TestAcceptor2", "dummy")};

    StringPair[] TestORBInitRefData =
        {new StringPair("Foo", "ior:930492049394"),
            new StringPair("Bar", "ior:3453465785633576")};

    URL testServicesURL = null;
    String testServicesString = "corbaloc::camelot/NameService";

    try {
      testServicesURL = new URL(testServicesString);
    } catch (Exception exc) {
    }

    // propertyName,
    // operation,
    // fieldName, defaultValue,
    // testValue, testData (string or Pair[])
    ParserData[] pd = {
        ParserDataFactory.make(ORBConstants.DEBUG_PROPERTY,
            OperationFactory.listAction(",", OperationFactory.stringAction()),
            "debugFlags", new String[0],
            debugTestData, "subcontract,poa,transport"),
        ParserDataFactory.make(ORBConstants.INITIAL_HOST_PROPERTY,
            OperationFactory.stringAction(),
            "ORBInitialHost", "",
            "Foo", "Foo"),
        ParserDataFactory.make(ORBConstants.INITIAL_PORT_PROPERTY,
            OperationFactory.integerAction(),
            "ORBInitialPort", new Integer(ORBConstants.DEFAULT_INITIAL_PORT),
            new Integer(27314), "27314"),
        // Where did this come from?
        //ParserDataFactory.make( ORBConstants.INITIAL_PORT_PROPERTY,
        //OperationFactory.booleanAction(),
        //"ORBInitialPortInitialized", Boolean.FALSE,
        //Boolean.TRUE, "27314" ),
        ParserDataFactory.make(ORBConstants.SERVER_HOST_PROPERTY,
            OperationFactory.stringAction(),
            "ORBServerHost", "",
            "camelot", "camelot"),
        ParserDataFactory.make(ORBConstants.SERVER_PORT_PROPERTY,
            OperationFactory.integerAction(),
            "ORBServerPort", new Integer(0),
            new Integer(38143), "38143"),
        // NOTE: We are putting SERVER_HOST_NAME configuration info into
        // DataCollectorBase to avoid a security hole.  However, that forces
        // us to also set LISTEN_ON_ALL_INTERFACES at the same time.
        // This all needs to be cleaned up for two reasons: to get configuration
        // out of DataCollectorBase and to correctly support multihoming.
        ParserDataFactory.make(ORBConstants.LISTEN_ON_ALL_INTERFACES,
            OperationFactory.stringAction(),
            "listenOnAllInterfaces", ORBConstants.LISTEN_ON_ALL_INTERFACES,
            "foo", "foo"),
        ParserDataFactory.make(ORBConstants.ORB_ID_PROPERTY,
            OperationFactory.stringAction(),
            "orbId", "",
            "foo", "foo"),
        ParserDataFactory.make(ORBConstants.OLD_ORB_ID_PROPERTY,
            OperationFactory.stringAction(),
            "orbId", "",
            "foo", "foo"),
        ParserDataFactory.make(ORBConstants.ORB_SERVER_ID_PROPERTY,
            OperationFactory.integerAction(),
            "persistentServerId", new Integer(-1),
            new Integer(1234), "1234"),
        ParserDataFactory.make(
            ORBConstants.ORB_SERVER_ID_PROPERTY,
            OperationFactory.setFlagAction(),
            "persistentServerIdInitialized", Boolean.FALSE,
            Boolean.TRUE, "1234"),
        ParserDataFactory.make(
            ORBConstants.ORB_SERVER_ID_PROPERTY,
            OperationFactory.setFlagAction(),
            "orbServerIdPropertySpecified", Boolean.FALSE,
            Boolean.TRUE, "1234"),
        // REVISIT after switch
        // ParserDataFactory.make( ORBConstants.INITIAL_SERVICES_PROPERTY,
        // OperationFactory.URLAction(),
        // "servicesURL", null,
        // testServicesURL, testServicesString ),
        // ParserDataFactory.make( ORBConstants.DEFAULT_INIT_REF_PROPERTY,
        // OperationFactory.stringAction(),
        // "defaultInitRef", null,
        // "Fooref", "Fooref" ),
        ParserDataFactory.make(ORBConstants.HIGH_WATER_MARK_PROPERTY,
            OperationFactory.integerAction(),
            "highWaterMark", new Integer(240),
            new Integer(3745), "3745"),
        ParserDataFactory.make(ORBConstants.LOW_WATER_MARK_PROPERTY,
            OperationFactory.integerAction(),
            "lowWaterMark", new Integer(100),
            new Integer(12), "12"),
        ParserDataFactory.make(ORBConstants.NUMBER_TO_RECLAIM_PROPERTY,
            OperationFactory.integerAction(),
            "numberToReclaim", new Integer(5),
            new Integer(231), "231"),
        ParserDataFactory.make(ORBConstants.GIOP_VERSION,
            makeGVOperation(),
            "giopVersion", GIOPVersion.DEFAULT_VERSION,
            new GIOPVersion(2, 3), "2.3"),
        ParserDataFactory.make(ORBConstants.GIOP_FRAGMENT_SIZE,
            makeFSOperation(), "giopFragmentSize",
            new Integer(ORBConstants.GIOP_DEFAULT_FRAGMENT_SIZE),
            new Integer(65536), "65536"),
        ParserDataFactory.make(ORBConstants.GIOP_BUFFER_SIZE,
            OperationFactory.integerAction(),
            "giopBufferSize", new Integer(ORBConstants.GIOP_DEFAULT_BUFFER_SIZE),
            new Integer(234000), "234000"),
        ParserDataFactory.make(ORBConstants.GIOP_11_BUFFMGR,
            makeBMGROperation(),
            "giop11BuffMgr", new Integer(ORBConstants.DEFAULT_GIOP_11_BUFFMGR),
            new Integer(1), "CLCT"),
        ParserDataFactory.make(ORBConstants.GIOP_12_BUFFMGR,
            makeBMGROperation(),
            "giop12BuffMgr", new Integer(ORBConstants.DEFAULT_GIOP_12_BUFFMGR),
            new Integer(0), "GROW"),

        // Note that the same property is used to set two different
        // fields here.  This requires that both entries use the same test
        // data, or the test will fail.
        ParserDataFactory.make(ORBConstants.GIOP_TARGET_ADDRESSING,
            OperationFactory.compose(OperationFactory.integerRangeAction(0, 3),
                OperationFactory.convertIntegerToShort()),
            "giopTargetAddressPreference",
            new Short(ORBConstants.ADDR_DISP_HANDLE_ALL),
            new Short((short) 2), "2"),
        ParserDataFactory.make(ORBConstants.GIOP_TARGET_ADDRESSING,
            makeADOperation(),
            "giopAddressDisposition", new Short(KeyAddr.value),
            new Short((short) 2), "2"),
        ParserDataFactory.make(ORBConstants.ALWAYS_SEND_CODESET_CTX_PROPERTY,
            OperationFactory.booleanAction(),
            "alwaysSendCodeSetCtx", Boolean.TRUE,
            Boolean.FALSE, "false"),
        ParserDataFactory.make(ORBConstants.USE_BOMS,
            OperationFactory.booleanAction(),
            "useByteOrderMarkers",
            Boolean.valueOf(ORBConstants.DEFAULT_USE_BYTE_ORDER_MARKERS),
            Boolean.FALSE, "false"),
        ParserDataFactory.make(ORBConstants.USE_BOMS_IN_ENCAPS,
            OperationFactory.booleanAction(),
            "useByteOrderMarkersInEncaps",
            Boolean.valueOf(ORBConstants.DEFAULT_USE_BYTE_ORDER_MARKERS_IN_ENCAPS),
            Boolean.FALSE, "false"),
        ParserDataFactory.make(ORBConstants.CHAR_CODESETS,
            makeCSOperation(),
            "charData", CodeSetComponentInfo.JAVASOFT_DEFAULT_CODESETS.getCharComponent(),
            CodeSetComponentInfo.createFromString(codeSetTestString), codeSetTestString),
        ParserDataFactory.make(ORBConstants.WCHAR_CODESETS,
            makeCSOperation(),
            "wcharData", CodeSetComponentInfo.JAVASOFT_DEFAULT_CODESETS.getWCharComponent(),
            CodeSetComponentInfo.createFromString(codeSetTestString), codeSetTestString),
        ParserDataFactory.make(ORBConstants.ALLOW_LOCAL_OPTIMIZATION,
            OperationFactory.booleanAction(),
            "allowLocalOptimization", Boolean.FALSE,
            Boolean.TRUE, "true"),
        ParserDataFactory.make(ORBConstants.LEGACY_SOCKET_FACTORY_CLASS_PROPERTY,
            makeLegacySocketFactoryOperation(),
            // No default - must be set by user if they are using
            // legacy socket factory.
            "legacySocketFactory", null,
            new TestLegacyORBSocketFactory(),
            MY_CLASS_NAME + "$TestLegacyORBSocketFactory"),
        ParserDataFactory.make(ORBConstants.SOCKET_FACTORY_CLASS_PROPERTY,
            makeSocketFactoryOperation(),
            "socketFactory", new DefaultSocketFactoryImpl(),
            new TestORBSocketFactory(),
            MY_CLASS_NAME + "$TestORBSocketFactory"),
        ParserDataFactory.make(ORBConstants.LISTEN_SOCKET_PROPERTY,
            makeUSLOperation(),
            "userSpecifiedListenPorts", new USLPort[0],
            USLPorts, "FOO:2701,BAR:3333"),
        ParserDataFactory.make(ORBConstants.IOR_TO_SOCKET_INFO_CLASS_PROPERTY,
            makeIORToSocketInfoOperation(),
            "iorToSocketInfo", new DefaultIORToSocketInfoImpl(),
            new TestIORToSocketInfo(),
            MY_CLASS_NAME + "$TestIORToSocketInfo"),
        ParserDataFactory.make(ORBConstants.IIOP_PRIMARY_TO_CONTACT_INFO_CLASS_PROPERTY,
            makeIIOPPrimaryToContactInfoOperation(),
            "iiopPrimaryToContactInfo", null,
            new TestIIOPPrimaryToContactInfo(),
            MY_CLASS_NAME + "$TestIIOPPrimaryToContactInfo"),
        ParserDataFactory.make(ORBConstants.CONTACT_INFO_LIST_FACTORY_CLASS_PROPERTY,
            makeContactInfoListFactoryOperation(),
            "corbaContactInfoListFactory", null,
            new TestContactInfoListFactory(),
            MY_CLASS_NAME + "$TestContactInfoListFactory"),
        ParserDataFactory.make(ORBConstants.PERSISTENT_SERVER_PORT_PROPERTY,
            OperationFactory.integerAction(),
            "persistentServerPort", new Integer(0),
            new Integer(2743), "2743"),
        ParserDataFactory.make(ORBConstants.PERSISTENT_SERVER_PORT_PROPERTY,
            OperationFactory.setFlagAction(),
            "persistentPortInitialized", Boolean.FALSE,
            Boolean.TRUE, "2743"),
        ParserDataFactory.make(ORBConstants.SERVER_ID_PROPERTY,
            OperationFactory.integerAction(),
            "persistentServerId", new Integer(0),
            new Integer(294), "294"),
        ParserDataFactory.make(ORBConstants.SERVER_ID_PROPERTY,
            OperationFactory.setFlagAction(),
            "persistentServerIdInitialized", Boolean.FALSE,
            Boolean.TRUE, "294"),
        ParserDataFactory.make(ORBConstants.SERVER_ID_PROPERTY,
            OperationFactory.setFlagAction(),
            "orbServerIdPropertySpecified", Boolean.FALSE,
            Boolean.TRUE, "294"),
        ParserDataFactory.make(ORBConstants.ACTIVATED_PROPERTY,
            OperationFactory.booleanAction(),
            "serverIsORBActivated", Boolean.FALSE,
            Boolean.TRUE, "true"),
        ParserDataFactory.make(ORBConstants.BAD_SERVER_ID_HANDLER_CLASS_PROPERTY,
            OperationFactory.classAction(),
            "badServerIdHandlerClass", null,
            TestBadServerIdHandler.class, MY_CLASS_NAME + "$TestBadServerIdHandler"),
        ParserDataFactory.make(ORBConstants.PI_ORB_INITIALIZER_CLASS_PREFIX,
            makeROIOperation(),
            "orbInitializers", new ORBInitializer[0],
            TestORBInitializers, TestORBInitData, ORBInitializer.class),
        ParserDataFactory.make(ORBConstants.ACCEPTOR_CLASS_PREFIX_PROPERTY,
            makeAcceptorInstantiationOperation(),
            "acceptors", new Acceptor[0],
            TestAcceptors, TestAcceptorData, Acceptor.class),

        //
        // Socket/Channel control
        //

        // Acceptor:
        // useNIOSelector == true
        //   useSelectThreadToWait = true
        //   useWorkerThreadForEvent = false
        // else
        //   useSelectThreadToWait = false
        //   useWorkerThreadForEvent = true

        // Connection:
        // useNIOSelector == true
        //   useSelectThreadToWait = true
        //   useWorkerThreadForEvent = true
        // else
        //   useSelectThreadToWait = false
        //   useWorkerThreadForEvent = true

        ParserDataFactory.make(ORBConstants.ACCEPTOR_SOCKET_TYPE_PROPERTY,
            OperationFactory.stringAction(),
            "acceptorSocketType", ORBConstants.SOCKETCHANNEL,
            "foo", "foo"),

        ParserDataFactory.make(ORBConstants.USE_NIO_SELECT_TO_WAIT_PROPERTY,
            OperationFactory.booleanAction(),
            "acceptorSocketUseSelectThreadToWait", Boolean.TRUE,
            Boolean.TRUE, "true"),
        ParserDataFactory.make(ORBConstants.ACCEPTOR_SOCKET_USE_WORKER_THREAD_FOR_EVENT_PROPERTY,
            OperationFactory.booleanAction(),
            "acceptorSocketUseWorkerThreadForEvent", Boolean.TRUE,
            Boolean.TRUE, "true"),
        ParserDataFactory.make(ORBConstants.CONNECTION_SOCKET_TYPE_PROPERTY,
            OperationFactory.stringAction(),
            "connectionSocketType", ORBConstants.SOCKETCHANNEL,
            "foo", "foo"),
        ParserDataFactory.make(ORBConstants.USE_NIO_SELECT_TO_WAIT_PROPERTY,
            OperationFactory.booleanAction(),
            "connectionSocketUseSelectThreadToWait", Boolean.TRUE,
            Boolean.TRUE, "true"),
        ParserDataFactory.make(ORBConstants.CONNECTION_SOCKET_USE_WORKER_THREAD_FOR_EVENT_PROPERTY,
            OperationFactory.booleanAction(),
            "connectionSocketUseWorkerThreadForEvent", Boolean.TRUE,
            Boolean.TRUE, "true"),
        ParserDataFactory.make(ORBConstants.DISABLE_DIRECT_BYTE_BUFFER_USE_PROPERTY,
            OperationFactory.booleanAction(),
            "disableDirectByteBufferUse", Boolean.FALSE,
            Boolean.TRUE, "true"),
        ParserDataFactory.make(ORBConstants.TRANSPORT_TCP_READ_TIMEOUTS_PROPERTY,
            makeTTCPRTOperation(),
            "readTimeouts", TransportDefault.makeReadTimeoutsFactory().create(
                ORBConstants.TRANSPORT_TCP_INITIAL_TIME_TO_WAIT,
                ORBConstants.TRANSPORT_TCP_MAX_TIME_TO_WAIT,
                ORBConstants.TRANSPORT_TCP_GIOP_HEADER_MAX_TIME_TO_WAIT,
                ORBConstants.TRANSPORT_TCP_TIME_TO_WAIT_BACKOFF_FACTOR),
            readTimeouts, "100:3000:300:20"),
        ParserDataFactory.make(
            ORBConstants.ENABLE_JAVA_SERIALIZATION_PROPERTY,
            OperationFactory.booleanAction(),
            "enableJavaSerialization", Boolean.FALSE,
            Boolean.FALSE, "false"),
        ParserDataFactory.make(
            ORBConstants.USE_REP_ID,
            OperationFactory.booleanAction(),
            "useRepId", Boolean.TRUE,
            Boolean.TRUE, "true"),
        ParserDataFactory.make(ORBConstants.ORB_INIT_REF_PROPERTY,
            OperationFactory.identityAction(),
            "orbInitialReferences", new StringPair[0],
            TestORBInitRefData, TestORBInitRefData, StringPair.class)
    };

    parserData = pd;
  }

  public final class TestBadServerIdHandler implements BadServerIdHandler {

    public boolean equals(Object other) {
      return other instanceof TestBadServerIdHandler;
    }

    public int hashCode() {
      return 1;
    }

    public void handle(ObjectKey objectKey) {
    }
  }

  private Operation makeTTCPRTOperation() {
    Operation[] fourIop = {OperationFactory.integerAction(),
        OperationFactory.integerAction(),
        OperationFactory.integerAction(),
        OperationFactory.integerAction()};

    Operation op2 = OperationFactory.sequenceAction(":", fourIop);

    Operation rtOp = new Operation() {
      public Object operate(Object value) {
        Object[] values = (Object[]) value;
        Integer initialTime = (Integer) (values[0]);
        Integer maxGIOPHdrTime = (Integer) (values[1]);
        Integer maxGIOPBodyTime = (Integer) (values[2]);
        Integer backoffPercent = (Integer) (values[3]);
        return TransportDefault.makeReadTimeoutsFactory().create(
            initialTime.intValue(),
            maxGIOPHdrTime.intValue(),
            maxGIOPBodyTime.intValue(),
            backoffPercent.intValue());
      }
    };

    Operation ttcprtOp = OperationFactory.compose(op2, rtOp);
    return ttcprtOp;
  }

  private Operation makeUSLOperation() {
    Operation[] siop = {OperationFactory.stringAction(),
        OperationFactory.integerAction()};
    Operation op2 = OperationFactory.sequenceAction(":", siop);

    Operation uslop = new Operation() {
      public Object operate(Object value) {
        Object[] values = (Object[]) value;
        String type = (String) (values[0]);
        Integer port = (Integer) (values[1]);
        return new USLPort(type, port.intValue());
      }
    };

    Operation op3 = OperationFactory.compose(op2, uslop);
    Operation listenop = OperationFactory.listAction(",", op3);
    return listenop;
  }

  public static final class TestLegacyORBSocketFactory
      implements com.sun.corba.se.spi.legacy.connection.ORBSocketFactory {

    public boolean equals(Object other) {
      return other instanceof TestLegacyORBSocketFactory;
    }

    public int hashCode() {
      return 1;
    }

    public ServerSocket createServerSocket(String type, int port) {
      return null;
    }

    public SocketInfo getEndPointInfo(org.omg.CORBA.ORB orb,
        IOR ior, SocketInfo socketInfo) {
      return null;
    }

    public Socket createSocket(SocketInfo socketInfo) {
      return null;
    }
  }

  public static final class TestORBSocketFactory
      implements com.sun.corba.se.spi.transport.ORBSocketFactory {

    public boolean equals(Object other) {
      return other instanceof TestORBSocketFactory;
    }

    public int hashCode() {
      return 1;
    }

    public void setORB(ORB orb) {
    }

    public ServerSocket createServerSocket(String type, InetSocketAddress a) {
      return null;
    }

    public Socket createSocket(String type, InetSocketAddress a) {
      return null;
    }

    public void setAcceptedSocketOptions(Acceptor acceptor,
        ServerSocket serverSocket,
        Socket socket) {
    }
  }

  public static final class TestIORToSocketInfo
      implements IORToSocketInfo {

    public boolean equals(Object other) {
      return other instanceof TestIORToSocketInfo;
    }

    public int hashCode() {
      return 1;
    }

    public List getSocketInfo(IOR ior) {
      return null;
    }
  }

  public static final class TestIIOPPrimaryToContactInfo
      implements IIOPPrimaryToContactInfo {

    public void reset(ContactInfo primary) {
    }

    public boolean hasNext(ContactInfo primary,
        ContactInfo previous,
        List contactInfos) {
      return true;
    }

    public ContactInfo next(ContactInfo primary,
        ContactInfo previous,
        List contactInfos) {
      return null;
    }
  }

  public static final class TestContactInfoListFactory
      implements CorbaContactInfoListFactory {

    public boolean equals(Object other) {
      return other instanceof TestContactInfoListFactory;
    }

    public int hashCode() {
      return 1;
    }

    public void setORB(ORB orb) {
    }

    public CorbaContactInfoList create(IOR ior) {
      return null;
    }
  }

  private Operation makeMapOperation(final Map map) {
    return new Operation() {
      public Object operate(Object value) {
        return map.get(value);
      }
    };
  }

  private Operation makeBMGROperation() {
    Map map = new HashMap();
    map.put("GROW", new Integer(0));
    map.put("CLCT", new Integer(1));
    map.put("STRM", new Integer(2));
    return makeMapOperation(map);
  }

  private Operation makeLegacySocketFactoryOperation() {
    Operation sfop = new Operation() {
      public Object operate(Object value) {
        String param = (String) value;

        try {
          Class<?> legacySocketFactoryClass =
              SharedSecrets.getJavaCorbaAccess().loadClass(param);
          // For security reasons avoid creating an instance if
          // this socket factory class is not one that would fail
          // the class cast anyway.
          if (com.sun.corba.se.spi.legacy.connection.ORBSocketFactory.class
              .isAssignableFrom(legacySocketFactoryClass)) {
            return legacySocketFactoryClass.newInstance();
          } else {
            throw wrapper.illegalSocketFactoryType(legacySocketFactoryClass.toString());
          }
        } catch (Exception ex) {
          // ClassNotFoundException, IllegalAccessException,
          // InstantiationException, SecurityException or
          // ClassCastException
          throw wrapper.badCustomSocketFactory(ex, param);
        }
      }
    };

    return sfop;
  }

  private Operation makeSocketFactoryOperation() {
    Operation sfop = new Operation() {
      public Object operate(Object value) {
        String param = (String) value;

        try {
          Class<?> socketFactoryClass =
              SharedSecrets.getJavaCorbaAccess().loadClass(param);
          // For security reasons avoid creating an instance if
          // this socket factory class is not one that would fail
          // the class cast anyway.
          if (com.sun.corba.se.spi.transport.ORBSocketFactory.class
              .isAssignableFrom(socketFactoryClass)) {
            return socketFactoryClass.newInstance();
          } else {
            throw wrapper.illegalSocketFactoryType(socketFactoryClass.toString());
          }
        } catch (Exception ex) {
          // ClassNotFoundException, IllegalAccessException,
          // InstantiationException, SecurityException or
          // ClassCastException
          throw wrapper.badCustomSocketFactory(ex, param);
        }
      }
    };

    return sfop;
  }

  private Operation makeIORToSocketInfoOperation() {
    Operation op = new Operation() {
      public Object operate(Object value) {
        String param = (String) value;

        try {
          Class<?> iorToSocketInfoClass =
              SharedSecrets.getJavaCorbaAccess().loadClass(param);
          // For security reasons avoid creating an instance if
          // this socket factory class is not one that would fail
          // the class cast anyway.
          if (IORToSocketInfo.class.isAssignableFrom(iorToSocketInfoClass)) {
            return iorToSocketInfoClass.newInstance();
          } else {
            throw wrapper.illegalIorToSocketInfoType(iorToSocketInfoClass.toString());
          }
        } catch (Exception ex) {
          // ClassNotFoundException, IllegalAccessException,
          // InstantiationException, SecurityException or
          // ClassCastException
          throw wrapper.badCustomIorToSocketInfo(ex, param);
        }
      }
    };

    return op;
  }

  private Operation makeIIOPPrimaryToContactInfoOperation() {
    Operation op = new Operation() {
      public Object operate(Object value) {
        String param = (String) value;

        try {
          Class<?> iiopPrimaryToContactInfoClass =
              SharedSecrets.getJavaCorbaAccess().loadClass(param);
          // For security reasons avoid creating an instance if
          // this socket factory class is not one that would fail
          // the class cast anyway.
          if (IIOPPrimaryToContactInfo.class.isAssignableFrom(iiopPrimaryToContactInfoClass)) {
            return iiopPrimaryToContactInfoClass.newInstance();
          } else {
            throw wrapper
                .illegalIiopPrimaryToContactInfoType(iiopPrimaryToContactInfoClass.toString());
          }
        } catch (Exception ex) {
          // ClassNotFoundException, IllegalAccessException,
          // InstantiationException, SecurityException or
          // ClassCastException
          throw wrapper.badCustomIiopPrimaryToContactInfo(ex, param);
        }
      }
    };

    return op;
  }

  private Operation makeContactInfoListFactoryOperation() {
    Operation op = new Operation() {
      public Object operate(Object value) {
        String param = (String) value;

        try {
          Class<?> contactInfoListFactoryClass =
              SharedSecrets.getJavaCorbaAccess().loadClass(param);
          // For security reasons avoid creating an instance if
          // this socket factory class is not one that would fail
          // the class cast anyway.
          if (CorbaContactInfoListFactory.class.isAssignableFrom(
              contactInfoListFactoryClass)) {
            return contactInfoListFactoryClass.newInstance();
          } else {
            throw wrapper.illegalContactInfoListFactoryType(
                contactInfoListFactoryClass.toString());
          }
        } catch (Exception ex) {
          // ClassNotFoundException, IllegalAccessException,
          // InstantiationException, SecurityException or
          // ClassCastException
          throw wrapper.badContactInfoListFactory(ex, param);
        }
      }
    };

    return op;
  }

  private Operation makeCSOperation() {
    Operation csop = new Operation() {
      public Object operate(Object value) {
        String val = (String) value;
        return CodeSetComponentInfo.createFromString(val);
      }
    };

    return csop;
  }

  private Operation makeADOperation() {
    Operation admap = new Operation() {
      private Integer[] map = {
          new Integer(KeyAddr.value),
          new Integer(ProfileAddr.value),
          new Integer(ReferenceAddr.value),
          new Integer(KeyAddr.value)};

      public Object operate(Object value) {
        int val = ((Integer) value).intValue();
        return map[val];
      }
    };

    Operation rangeop = OperationFactory.integerRangeAction(0, 3);
    Operation op1 = OperationFactory.compose(rangeop, admap);
    Operation result = OperationFactory.compose(op1, OperationFactory.convertIntegerToShort());
    return result;
  }

  private Operation makeFSOperation() {
    Operation fschecker = new Operation() {
      public Object operate(Object value) {
        int giopFragmentSize = ((Integer) value).intValue();
        if (giopFragmentSize < ORBConstants.GIOP_FRAGMENT_MINIMUM_SIZE) {
          throw wrapper.fragmentSizeMinimum(new Integer(giopFragmentSize),
              new Integer(ORBConstants.GIOP_FRAGMENT_MINIMUM_SIZE));
        }

        if (giopFragmentSize % ORBConstants.GIOP_FRAGMENT_DIVISOR != 0) {
          throw wrapper.fragmentSizeDiv(new Integer(giopFragmentSize),
              new Integer(ORBConstants.GIOP_FRAGMENT_DIVISOR));
        }

        return value;
      }
    };

    Operation result = OperationFactory.compose(OperationFactory.integerAction(),
        fschecker);
    return result;
  }

  private Operation makeGVOperation() {
    Operation gvHelper = OperationFactory.listAction(".",
        OperationFactory.integerAction());
    Operation gvMain = new Operation() {
      public Object operate(Object value) {
        Object[] nums = (Object[]) value;
        int major = ((Integer) (nums[0])).intValue();
        int minor = ((Integer) (nums[1])).intValue();

        return new GIOPVersion(major, minor);
      }
    };

    Operation result = OperationFactory.compose(gvHelper, gvMain);
    return result;
  }

  public static final class TestORBInitializer1 extends org.omg.CORBA.LocalObject
      implements ORBInitializer {

    public boolean equals(Object other) {
      return other instanceof TestORBInitializer1;
    }

    public int hashCode() {
      return 1;
    }

    public void pre_init(ORBInitInfo info) {
    }

    public void post_init(ORBInitInfo info) {
    }
  }

  public static final class TestORBInitializer2 extends org.omg.CORBA.LocalObject
      implements ORBInitializer {

    public boolean equals(Object other) {
      return other instanceof TestORBInitializer2;
    }

    public int hashCode() {
      return 1;
    }

    public void pre_init(ORBInitInfo info) {
    }

    public void post_init(ORBInitInfo info) {
    }
  }

  private Operation makeROIOperation() {
    Operation clsop = OperationFactory.classAction();
    Operation indexOp = OperationFactory.suffixAction();
    Operation op1 = OperationFactory.compose(indexOp, clsop);
    Operation mop = OperationFactory.maskErrorAction(op1);

    Operation mkinst = new Operation() {
      public Object operate(Object value) {
        final Class initClass = (Class) value;
        if (initClass == null) {
          return null;
        }

        // For security reasons avoid creating an instance
        // if this class is one that would fail the class cast
        // to ORBInitializer anyway.
        if (org.omg.PortableInterceptor.ORBInitializer.class.isAssignableFrom(
            initClass)) {
          // Now that we have a class object, instantiate one and
          // remember it:
          ORBInitializer initializer = null;

          try {
            initializer = (ORBInitializer) AccessController.doPrivileged(
                new PrivilegedExceptionAction() {
                  public Object run()
                      throws InstantiationException, IllegalAccessException {
                    return initClass.newInstance();
                  }
                }
            );
          } catch (PrivilegedActionException exc) {
            // Unwrap the exception, as we don't care exc here
            throw wrapper.orbInitializerFailure(exc.getException(),
                initClass.getName());
          } catch (Exception exc) {
            throw wrapper.orbInitializerFailure(exc, initClass.getName());
          }

          return initializer;
        } else {
          throw wrapper.orbInitializerType(initClass.getName());
        }
      }
    };

    Operation result = OperationFactory.compose(mop, mkinst);

    return result;
  }

  public static final class TestAcceptor1
      implements Acceptor {

    public boolean equals(Object other) {
      return other instanceof TestAcceptor1;
    }

    public int hashCode() {
      return 1;
    }

    public boolean initialize() {
      return true;
    }

    public boolean initialized() {
      return true;
    }

    public String getConnectionCacheType() {
      return "FOO";
    }

    public void setConnectionCache(InboundConnectionCache connectionCache) {
    }

    public InboundConnectionCache getConnectionCache() {
      return null;
    }

    public boolean shouldRegisterAcceptEvent() {
      return true;
    }

    public void setUseSelectThreadForConnections(boolean x) {
    }

    public boolean shouldUseSelectThreadForConnections() {
      return true;
    }

    public void setUseWorkerThreadForConnections(boolean x) {
    }

    public boolean shouldUseWorkerThreadForConnections() {
      return true;
    }

    public void accept() {
    }

    public void close() {
    }

    public EventHandler getEventHandler() {
      return null;
    }

    public MessageMediator createMessageMediator(
        Broker xbroker, Connection xconnection) {
      return null;
    }

    public MessageMediator finishCreatingMessageMediator(
        Broker xbroker, Connection xconnection,
        MessageMediator messageMediator) {
      return null;
    }

    public InputObject createInputObject(
        Broker broker, MessageMediator messageMediator) {
      return null;
    }

    public OutputObject createOutputObject(
        Broker broker, MessageMediator messageMediator) {
      return null;
    }
  }

  public static final class TestAcceptor2
      implements Acceptor {

    public boolean equals(Object other) {
      return other instanceof TestAcceptor2;
    }

    public int hashCode() {
      return 1;
    }

    public boolean initialize() {
      return true;
    }

    public boolean initialized() {
      return true;
    }

    public String getConnectionCacheType() {
      return "FOO";
    }

    public void setConnectionCache(InboundConnectionCache connectionCache) {
    }

    public InboundConnectionCache getConnectionCache() {
      return null;
    }

    public boolean shouldRegisterAcceptEvent() {
      return true;
    }

    public void setUseSelectThreadForConnections(boolean x) {
    }

    public boolean shouldUseSelectThreadForConnections() {
      return true;
    }

    public void setUseWorkerThreadForConnections(boolean x) {
    }

    public boolean shouldUseWorkerThreadForConnections() {
      return true;
    }

    public void accept() {
    }

    public void close() {
    }

    public EventHandler getEventHandler() {
      return null;
    }

    public MessageMediator createMessageMediator(
        Broker xbroker, Connection xconnection) {
      return null;
    }

    public MessageMediator finishCreatingMessageMediator(
        Broker xbroker, Connection xconnection,
        MessageMediator messageMediator) {
      return null;
    }

    public InputObject createInputObject(
        Broker broker, MessageMediator messageMediator) {
      return null;
    }

    public OutputObject createOutputObject(
        Broker broker, MessageMediator messageMediator) {
      return null;
    }
  }

  // REVISIT - this is a cut and paste modification of makeROIOperation.
  private Operation makeAcceptorInstantiationOperation() {
    Operation clsop = OperationFactory.classAction();
    Operation indexOp = OperationFactory.suffixAction();
    Operation op1 = OperationFactory.compose(indexOp, clsop);
    Operation mop = OperationFactory.maskErrorAction(op1);

    Operation mkinst = new Operation() {
      public Object operate(Object value) {
        final Class initClass = (Class) value;
        if (initClass == null) {
          return null;
        }

        // For security reasons avoid creating an instance
        // if this class is one that would fail the class cast
        // to ORBInitializer anyway.
        if (Acceptor.class.isAssignableFrom(initClass)) {
          // Now that we have a class object, instantiate one and
          // remember it:
          Acceptor acceptor = null;

          try {
            acceptor = (Acceptor) AccessController.doPrivileged(
                new PrivilegedExceptionAction() {
                  public Object run()
                      throws InstantiationException, IllegalAccessException {
                    return initClass.newInstance();
                  }
                }
            );
          } catch (PrivilegedActionException exc) {
            // Unwrap the exception, as we don't care exc here
            throw wrapper.acceptorInstantiationFailure(exc.getException(),
                initClass.getName());
          } catch (Exception exc) {
            throw wrapper.acceptorInstantiationFailure(exc, initClass.getName());
          }

          return acceptor;
        } else {
          throw wrapper.acceptorInstantiationTypeFailure(initClass.getName());
        }
      }
    };

    Operation result = OperationFactory.compose(mop, mkinst);

    return result;
  }

  private Operation makeInitRefOperation() {
    return new Operation() {
      public Object operate(Object value) {
        // Object is String[] of length 2.
        String[] values = (String[]) value;
        if (values.length != 2) {
          throw wrapper.orbInitialreferenceSyntax();
        }

        return values[0] + "=" + values[1];
      }
    };
  }
}

// End of file.
